package com.wasu.sdk_ott.service

import android.app.AlarmManager
import android.app.PendingIntent
import android.app.Service
import android.content.Context
import android.content.Intent
import android.database.Cursor
import android.database.sqlite.SQLiteDatabase
import android.util.Log
import com.alibaba.fastjson.JSONObject
import com.wasu.UILApplication
import com.wasu.constant.TAG
import com.wasu.sdk_ott.http.live.verifyAuthorizeChannel
import com.wasu.sdk_ott.provider.RESERVATION_CONDITION
import com.wasu.sdk_ott.provider.RESERVATION_CONTENT_URI
import com.wasu.sdk_ott.provider.RESERVATION_DB_CHID
import com.wasu.sdk_ott.provider.RESERVATION_DB_CHNAME
import com.wasu.sdk_ott.provider.RESERVATION_DB_EDIT
import com.wasu.sdk_ott.provider.RESERVATION_DB_ENDDATE
import com.wasu.sdk_ott.provider.RESERVATION_DB_STARTDATE
import com.wasu.sdk_ott.provider.RESERVATION_DB_TABLE
import com.wasu.sdk_ott.provider.RESERVATION_SORT
import io.reactivex.Observable
import io.reactivex.ObservableOnSubscribe
import io.reactivex.Observer
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import java.util.Arrays

/**
 * <p>------------------------------------------------------
 * <p>Copyright (C) 2020 wasu company, All rights reserved.
 * <p>------------------------------------------------------
 * <p> 关于节目单预约相关，数据库查询和删除，广播发送到UI等
 * <p>
 *
 * @author Created by zhangmz
 * @date on 2023/9/5
 */
object LiveReservationHelper {

    /**
     * 是否已经启动预约节目单服务
     */
    private var isStartReservationService = false

    /**
     * 启动轮询查询预约节目单服务
     * 间隔一分钟
     */
    fun startReservationService(context: Context){
        Log.v(TAG, "startReservationService, isStartReservationService:$isStartReservationService")
        if (isStartReservationService){
            return
        }
        context.startService(Intent(context, LiveReservationEpService::class.java))
        isStartReservationService = true
    }

    fun stopReservationService(context: Context){
        Log.v(TAG, "stopReservationService, isStartReservationService:$isStartReservationService")
        if (!isStartReservationService){
            return
        }
        context.stopService(Intent(context, LiveReservationEpService::class.java))
        isStartReservationService = false
        if (alarmManager == null || pendingIntent == null){
            Log.e(TAG, "alarm manager start not yet")
            return
        }
        alarmManager?.cancel(pendingIntent) ?: Log.e(TAG, "cancelVersionService, alarmManager can not be null")
    }

    /**
     * cp查询，删除过期的预约，并定时发送消息到service
     * @param selection 匹配字段
     * @param selectionArgs 查询
     * @param isFirst 是否首次在Application中调用，true:会删除过期所有节目单，false:标识已经删除过期后的，取最近一个即将到期节目单即可
     */
    fun queryEpReservation(
        context: Context,
        delete: () -> Unit = {  },
        selection: String? = null,
        selectionArgs: Array<String>? = null,
        isFirst: Boolean? = true
    ){
        Log.v(TAG, "queryEpReservation, isFirst:$isFirst; selection:$selection; selectionArgs:${Arrays.toString(selectionArgs)}; context:$context")
        Observable.create(ObservableOnSubscribe<String> { emitter ->
            // 首次开机，先删除过期预约，再取即将到期预约，开始计时
            if (isFirst == true){
                val param = arrayOf(RESERVATION_DB_CHID, RESERVATION_DB_CHNAME, RESERVATION_DB_STARTDATE, RESERVATION_DB_ENDDATE, RESERVATION_DB_EDIT)
                val cursor = context.contentResolver.query(RESERVATION_CONTENT_URI, param, selection, selectionArgs, RESERVATION_SORT)

                runCatching {
                    var isHaveInvalidData = false
                    var startdate: Long? = null
                    while (cursor?.moveToNext() == true){
                        val index = cursor.getColumnIndex(RESERVATION_DB_STARTDATE)
                        startdate = cursor.getLong(index)
                        if (startdate - RESERVATION_CONDITION < System.currentTimeMillis()) {
                            isHaveInvalidData = true
                        }else {
                            Log.v(TAG, "存在预约未到期节目单，跳过 while 循环 delay:${startdate - RESERVATION_CONDITION}")
                            break
                        }
                    }
                    Log.v(TAG, "isHaveInvalidData:$isHaveInvalidData; startdate:$startdate")
                    if (isHaveInvalidData && startdate != null){
                        context.contentResolver.delete(RESERVATION_CONTENT_URI, "$RESERVATION_DB_STARTDATE<=?", arrayOf(startdate.toString()))
                    }
                    emitter.onNext(createEpReservationParam(cursor))
                    cursor?.close()
                }.onFailure { e ->
                    cursor?.close()
                    emitter.onError(e)
                }
            }else {
                delete()
                val param = arrayOf(RESERVATION_DB_CHID, RESERVATION_DB_CHNAME, RESERVATION_DB_STARTDATE, RESERVATION_DB_ENDDATE, RESERVATION_DB_EDIT)
                val cursor = context.contentResolver.query(RESERVATION_CONTENT_URI, param, selection, selectionArgs, RESERVATION_SORT)
                if (cursor?.moveToFirst() == true){
                    emitter.onNext(createEpReservationParam(cursor))
                }
                cursor?.close()
            }
            emitter.onComplete()
        }).subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : Observer<String> {
                override fun onSubscribe(d: Disposable) { }
                override fun onNext(t: String) {
                    Log.v(TAG, "queryEpReservation1, onNext, result:$t")
                    if (t.isEmpty()){
                        return
                    }
                    val r = JSONObject.parseObject(t)
                    // 以最后一个未过期的节目单开始时间作为间隔，启动定时器，进入服务
                    val startdate = r.getLongValue(RESERVATION_DB_STARTDATE)
                    val chId = r.getString(RESERVATION_DB_CHID)
                    startEpAlarmManager(context, startdate - RESERVATION_CONDITION, chId, startdate, t)
                }
                override fun onError(e: Throwable) { Log.e(TAG, "queryEpReservation1, error:$e") }
                override fun onComplete() { }
            })
    }

    /**
     * 数据库查询
     * @param selection 匹配字段
     * @param selectionArgs 查询
     */
    fun queryEpReservation(
        context: Context?,
        db: SQLiteDatabase,
        selection: String? = null,
        selectionArgs: Array<String>? = null
    ){
        Log.v(TAG, "queryEpReservation, selection:$selection; selectionArgs:$selectionArgs; db:$db")
        Observable.create(ObservableOnSubscribe<String> { emitter ->
            val param = arrayOf(RESERVATION_DB_CHID, RESERVATION_DB_CHNAME, RESERVATION_DB_STARTDATE, RESERVATION_DB_ENDDATE, RESERVATION_DB_EDIT)
            val cursor = db.query(RESERVATION_DB_TABLE, param, selection, selectionArgs, null, null, RESERVATION_SORT)
            if (cursor?.moveToFirst() == true){
                emitter.onNext(createEpReservationParam(cursor))
            }
            cursor?.close()
            emitter.onComplete()
        }).subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : Observer<String> {
                override fun onSubscribe(d: Disposable) { }
                override fun onNext(t: String) {
                    Log.v(TAG, "queryEpReservation2, onNext, result:$t")
                    if (t.isEmpty()){
                        return
                    }
                    val r = JSONObject.parseObject(t)
                    // 以最后一个未过期的节目单开始时间作为间隔，启动定时器，进入服务
                    val startdate = r.getLongValue(RESERVATION_DB_STARTDATE)
                    val chId = r.getString(RESERVATION_DB_CHID)
                    startEpAlarmManager(context, startdate - RESERVATION_CONDITION, chId, startdate, t)
                }
                override fun onError(e: Throwable) { Log.e(TAG, "queryEpReservation2, error:$e") }
                override fun onComplete() { }
            })
    }

    /**
     * 按条件删除预约节目单表
     * @param where 匹配字段
     * @param selectionArgs 删除条件
     */
    fun deleteEpReservation(
        context: Context,
        where: String? = null,
        selectionArgs: Array<String>? = null
    ){
        Log.v(TAG, "deleteEpReservation, where:$where; selectionArgs:${Arrays.toString(selectionArgs)}; context:$context")
        if (selectionArgs.isNullOrEmpty()){
            return
        }
        context.contentResolver.delete(RESERVATION_CONTENT_URI, where, selectionArgs)
    }

    private var alarmManager: AlarmManager? = null
    private var pendingIntent: PendingIntent? = null

    /**
     * 定时启动服务，通知UI层预约节目单到时
     */
    private fun startEpAlarmManager(
        context: Context? = UILApplication.getInstance().application.applicationContext,
        delayTime: Long,
        chId: String? = "",
        startDate: Long? = null,
        value: String? = ""
    ){
        Log.v(TAG, "--startAlarmManager--delayTime:$delayTime; value:$value; context:$context")
        if (pendingIntent != null && alarmManager != null){
            alarmManager?.cancel(pendingIntent)
            Log.v(TAG, "cancel already start alarmManager, restart manager")
        }
        if (delayTime <= 0){
            Log.v(TAG, "startEpAlarmManager, alarm manager delay time must be greater than 0")
            return
        }
        alarmManager = context?.getSystemService(Service.ALARM_SERVICE) as? AlarmManager
        pendingIntent =  PendingIntent.getService(
            context,
            0,
            Intent(context, LiveReservationEpService::class.java).apply {
                putExtra(RESERVATION_DB_CHID, chId)
                putExtra(RESERVATION_DB_STARTDATE, startDate)
                putExtra("Schedual_ep", value)
            },
            PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE
        )
        alarmManager?.setExact(
            AlarmManager.RTC_WAKEUP,
            delayTime,
            pendingIntent
        ) ?: Log.e(TAG, "restartVersionService, alarmManager can not be null")
    }

    /**
     * 预约时间到，发送广播到UI层
     */
    fun sendEpReservationReceiver(
        context: Context,
        chId: String? = "",
        paramStr: String? = null
    ){
        verifyAuthorizeChannel(channelId = chId) {
            Log.v(TAG, "sendEpReservationReceiver, 验证通过，send 广播")
            context.sendBroadcast(Intent().apply {
                action = "com.wasu.schedual_ep_tip"
                putExtra("Schedual_ep", paramStr)
            })
        }
    }

    /**
     * 获得表中的参数，传给UI
     */
    private fun createEpReservationParam(
        cursor: Cursor? = null
    ): String {
        return runCatching {
            val param = JSONObject().apply {
                val index1 = cursor?.getColumnIndex(RESERVATION_DB_CHID)?: -1
                if (index1 >= 0){ put(RESERVATION_DB_CHID, cursor?.getString(index1)) }
                val index2 = cursor?.getColumnIndex(RESERVATION_DB_CHNAME)?: -1
                if (index2 >= 0){ put(RESERVATION_DB_CHNAME, cursor?.getString(index2)) }
                val index3 = cursor?.getColumnIndex(RESERVATION_DB_STARTDATE)?: -1
                if (index3 >= 0){ put(RESERVATION_DB_STARTDATE, cursor?.getLong(index3)) }
                val index4 = cursor?.getColumnIndex(RESERVATION_DB_ENDDATE)?: -1
                if (index4 >= 0){ put(RESERVATION_DB_ENDDATE, cursor?.getLong(index4)) }
                val index5 = cursor?.getColumnIndex(RESERVATION_DB_EDIT)?: -1
                if (index5 >= 0){ put(RESERVATION_DB_EDIT, cursor?.getString(index5)) }
            }
            param.toString()
        }.onFailure { e ->
            Log.e(TAG, "createEpReservationParam, cursor read string error:$e")
        }.getOrDefault("")
    }

}